{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:16:36.722067Z",
     "start_time": "2022-03-30T13:16:35.754640Z"
    }
   },
   "outputs": [],
   "source": [
    "import torch \n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:16:36.737027Z",
     "start_time": "2022-03-30T13:16:36.723065Z"
    }
   },
   "outputs": [],
   "source": [
    "data = pd.read_csv('./dataset/Income1.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:16:36.767945Z",
     "start_time": "2022-03-30T13:16:36.739023Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Unnamed: 0</th>\n",
       "      <th>Education</th>\n",
       "      <th>Income</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>26.658839</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>10.401338</td>\n",
       "      <td>27.306435</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>10.842809</td>\n",
       "      <td>22.132410</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>11.244147</td>\n",
       "      <td>21.169841</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>11.645485</td>\n",
       "      <td>15.192634</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>6</td>\n",
       "      <td>12.086957</td>\n",
       "      <td>26.398951</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7</td>\n",
       "      <td>12.488294</td>\n",
       "      <td>17.435307</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>8</td>\n",
       "      <td>12.889632</td>\n",
       "      <td>25.507885</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>9</td>\n",
       "      <td>13.290970</td>\n",
       "      <td>36.884595</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>10</td>\n",
       "      <td>13.732441</td>\n",
       "      <td>39.666109</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>11</td>\n",
       "      <td>14.133779</td>\n",
       "      <td>34.396281</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>12</td>\n",
       "      <td>14.535117</td>\n",
       "      <td>41.497994</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>13</td>\n",
       "      <td>14.976589</td>\n",
       "      <td>44.981575</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>14</td>\n",
       "      <td>15.377926</td>\n",
       "      <td>47.039595</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>15</td>\n",
       "      <td>15.779264</td>\n",
       "      <td>48.252578</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>16</td>\n",
       "      <td>16.220736</td>\n",
       "      <td>57.034251</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>17</td>\n",
       "      <td>16.622074</td>\n",
       "      <td>51.490919</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>18</td>\n",
       "      <td>17.023411</td>\n",
       "      <td>61.336621</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>19</td>\n",
       "      <td>17.464883</td>\n",
       "      <td>57.581988</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>20</td>\n",
       "      <td>17.866221</td>\n",
       "      <td>68.553714</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>21</td>\n",
       "      <td>18.267559</td>\n",
       "      <td>64.310925</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>22</td>\n",
       "      <td>18.709030</td>\n",
       "      <td>68.959009</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>23</td>\n",
       "      <td>19.110368</td>\n",
       "      <td>74.614639</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>24</td>\n",
       "      <td>19.511706</td>\n",
       "      <td>71.867195</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>24</th>\n",
       "      <td>25</td>\n",
       "      <td>19.913043</td>\n",
       "      <td>76.098135</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25</th>\n",
       "      <td>26</td>\n",
       "      <td>20.354515</td>\n",
       "      <td>75.775218</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>26</th>\n",
       "      <td>27</td>\n",
       "      <td>20.755853</td>\n",
       "      <td>72.486055</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>27</th>\n",
       "      <td>28</td>\n",
       "      <td>21.157191</td>\n",
       "      <td>77.355021</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>28</th>\n",
       "      <td>29</td>\n",
       "      <td>21.598662</td>\n",
       "      <td>72.118790</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>29</th>\n",
       "      <td>30</td>\n",
       "      <td>22.000000</td>\n",
       "      <td>80.260571</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    Unnamed: 0  Education     Income\n",
       "0            1  10.000000  26.658839\n",
       "1            2  10.401338  27.306435\n",
       "2            3  10.842809  22.132410\n",
       "3            4  11.244147  21.169841\n",
       "4            5  11.645485  15.192634\n",
       "5            6  12.086957  26.398951\n",
       "6            7  12.488294  17.435307\n",
       "7            8  12.889632  25.507885\n",
       "8            9  13.290970  36.884595\n",
       "9           10  13.732441  39.666109\n",
       "10          11  14.133779  34.396281\n",
       "11          12  14.535117  41.497994\n",
       "12          13  14.976589  44.981575\n",
       "13          14  15.377926  47.039595\n",
       "14          15  15.779264  48.252578\n",
       "15          16  16.220736  57.034251\n",
       "16          17  16.622074  51.490919\n",
       "17          18  17.023411  61.336621\n",
       "18          19  17.464883  57.581988\n",
       "19          20  17.866221  68.553714\n",
       "20          21  18.267559  64.310925\n",
       "21          22  18.709030  68.959009\n",
       "22          23  19.110368  74.614639\n",
       "23          24  19.511706  71.867195\n",
       "24          25  19.913043  76.098135\n",
       "25          26  20.354515  75.775218\n",
       "26          27  20.755853  72.486055\n",
       "27          28  21.157191  77.355021\n",
       "28          29  21.598662  72.118790\n",
       "29          30  22.000000  80.260571"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:16:36.892122Z",
     "start_time": "2022-03-30T13:16:36.769940Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Income')"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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caL/v4uLiwOu//nPf66RI0eqvr5e+fn5GjlypCQpPT1dLperx884fvy4ysrK9PTTT/vre/LJJ7Vjxw499dRTWrlypf/au+66S1/60pckSatWrdKll16q1tZWJSUl9ev3AhAetMgAGJCvfOUr2rdvX8Dr5ptv1rvvvqucnBx/iJGkgoKCft+/q0WmN/v379c111yjL3zhC0pNTdUZZ5whSTp48GDQn3HgwAG1t7frwgsv9B+Lj4/XtGnT9O677wZcO3nyZP9/Z2VlSZJaWlqC/iwA4UWLDIABGTZsmMaNGxfSz8bEdP6/lGEY/mPt7e0B1yQnJ5/yHkVFRRozZoyefPJJZWdny+fzKT8/XydOnAippr7Ex8f7/9vhcEiSvxsLQOTRIgNgUEyYMEGHDh2S2+32H9u9e3fANV3dPidf89lp0pMnT1ZlZWWPn/Hxxx+roaFBP/zhD3XxxRdrwoQJ/kHAXRISEiTJP6amJ2PHjlVCQoJ27drlP9be3q633npLeXl5p/gtAZiNFhkAA9LW1qampqaAY3FxcZo9e7bOOussXX/99brvvvvk9Xr1gx/8IOC6cePGKScnR3fccYfuuusuvf/++3rggQcCrlm9erUmTZqk73znO7r55puVkJCgnTt36mtf+5rS0tKUnp6uJ554QllZWTp48KBWrVoV8PMZGRlKTk5WRUWFRo0apaSkpG5Tr4cNG6bFixdr5cqVSktL0+jRo7V+/Xp9+umnWrRoURifFoBwo0UGwIBUVFQoKysr4DVz5kzFxMRo69at+sc//qFp06bpW9/6lu66666An42Pj9ezzz6r9957T5MnT9a9996rO++8M+Cas846S7/97W/1zjvvaNq0aSooKNCLL76ouLg4xcTE6LnnntPevXuVn5+v5cuX67777gv4+bi4OD3yyCP66U9/quzsbM2fP7/H3+Oee+5RcXGxrrvuOk2ZMkUffPCBtm/f7p9KDsCaHMbJndMAAAA2QosMAACwLYIMAACwLYIMAACwLYIMAACwLYIMAACwLYIMAACwLYIMAACwLYIMAACwLYIMAACwLYIMAACwLYIMAACwrf8HXBuPmJJneA0AAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(data.Education, data.Income)\n",
    "plt.xlabel('Education')\n",
    "plt.ylabel('Income')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:16:36.907080Z",
     "start_time": "2022-03-30T13:16:36.893118Z"
    }
   },
   "outputs": [],
   "source": [
    "# wx + b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:34:03.050154Z",
     "start_time": "2022-03-30T13:34:03.034197Z"
    }
   },
   "outputs": [],
   "source": [
    "# 分解写法\n",
    "w = torch.randn(1, requires_grad=True)\n",
    "b = torch.zeros(1, requires_grad=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:16:36.937000Z",
     "start_time": "2022-03-30T13:16:36.923037Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "A module that was compiled using NumPy 1.x cannot be run in\n",
      "NumPy 2.0.0 as it may crash. To support both 1.x and 2.x\n",
      "versions of NumPy, modules must be compiled with NumPy 2.0.\n",
      "Some module may need to rebuild instead e.g. with 'pybind11>=2.12'.\n",
      "\n",
      "If you are a user of the module, the easiest solution will be to\n",
      "downgrade to 'numpy<2' or try to upgrade the affected module.\n",
      "We expect that some modules will need time to support NumPy 2.\n",
      "\n",
      "Traceback (most recent call last):  File \"<frozen runpy>\", line 198, in _run_module_as_main\n",
      "  File \"<frozen runpy>\", line 88, in _run_code\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\ipykernel_launcher.py\", line 18, in <module>\n",
      "    app.launch_new_instance()\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\traitlets\\config\\application.py\", line 1075, in launch_instance\n",
      "    app.start()\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\ipykernel\\kernelapp.py\", line 739, in start\n",
      "    self.io_loop.start()\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\tornado\\platform\\asyncio.py\", line 205, in start\n",
      "    self.asyncio_loop.run_forever()\n",
      "  File \"D:\\developer\\Python312\\Lib\\asyncio\\base_events.py\", line 641, in run_forever\n",
      "    self._run_once()\n",
      "  File \"D:\\developer\\Python312\\Lib\\asyncio\\base_events.py\", line 1987, in _run_once\n",
      "    handle._run()\n",
      "  File \"D:\\developer\\Python312\\Lib\\asyncio\\events.py\", line 88, in _run\n",
      "    self._context.run(self._callback, *self._args)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\ipykernel\\kernelbase.py\", line 545, in dispatch_queue\n",
      "    await self.process_one()\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\ipykernel\\kernelbase.py\", line 534, in process_one\n",
      "    await dispatch(*args)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\ipykernel\\kernelbase.py\", line 437, in dispatch_shell\n",
      "    await result\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\ipykernel\\ipkernel.py\", line 362, in execute_request\n",
      "    await super().execute_request(stream, ident, parent)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\ipykernel\\kernelbase.py\", line 778, in execute_request\n",
      "    reply_content = await reply_content\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\ipykernel\\ipkernel.py\", line 449, in do_execute\n",
      "    res = shell.run_cell(\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\ipykernel\\zmqshell.py\", line 549, in run_cell\n",
      "    return super().run_cell(*args, **kwargs)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\core\\interactiveshell.py\", line 3075, in run_cell\n",
      "    result = self._run_cell(\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\core\\interactiveshell.py\", line 3130, in _run_cell\n",
      "    result = runner(coro)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\core\\async_helpers.py\", line 129, in _pseudo_sync_runner\n",
      "    coro.send(None)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\core\\interactiveshell.py\", line 3334, in run_cell_async\n",
      "    has_raised = await self.run_ast_nodes(code_ast.body, cell_name,\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\core\\interactiveshell.py\", line 3517, in run_ast_nodes\n",
      "    if await self.run_code(code, result, async_=asy):\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\core\\interactiveshell.py\", line 3577, in run_code\n",
      "    exec(code_obj, self.user_global_ns, self.user_ns)\n",
      "  File \"C:\\Windows\\temp\\ipykernel_18080\\624579656.py\", line 1, in <module>\n",
      "    w\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\core\\displayhook.py\", line 268, in __call__\n",
      "    format_dict, md_dict = self.compute_format_data(result)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\core\\displayhook.py\", line 157, in compute_format_data\n",
      "    return self.shell.display_formatter.format(result)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\core\\formatters.py\", line 182, in format\n",
      "    data = formatter(obj)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\decorator.py\", line 232, in fun\n",
      "    return caller(func, *(extras + args), **kw)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\core\\formatters.py\", line 226, in catch_format_error\n",
      "    r = method(self, *args, **kwargs)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\core\\formatters.py\", line 711, in __call__\n",
      "    printer.pretty(obj)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\lib\\pretty.py\", line 411, in pretty\n",
      "    return _repr_pprint(obj, self, cycle)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\IPython\\lib\\pretty.py\", line 779, in _repr_pprint\n",
      "    output = repr(obj)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\torch\\_tensor.py\", line 464, in __repr__\n",
      "    return torch._tensor_str._str(self, tensor_contents=tensor_contents)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\torch\\_tensor_str.py\", line 697, in _str\n",
      "    return _str_intern(self, tensor_contents=tensor_contents)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\torch\\_tensor_str.py\", line 617, in _str_intern\n",
      "    tensor_str = _tensor_str(self, indent)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\torch\\_tensor_str.py\", line 349, in _tensor_str\n",
      "    formatter = _Formatter(get_summarized_data(self) if summarize else self)\n",
      "  File \"D:\\developer\\Python312\\Lib\\site-packages\\torch\\_tensor_str.py\", line 138, in __init__\n",
      "    tensor_view, torch.isfinite(tensor_view) & tensor_view.ne(0)\n",
      "D:\\developer\\Python312\\Lib\\site-packages\\torch\\_tensor_str.py:138: UserWarning: Failed to initialize NumPy: _ARRAY_API not found (Triggered internally at ..\\torch\\csrc\\utils\\tensor_numpy.cpp:84.)\n",
      "  tensor_view, torch.isfinite(tensor_view) & tensor_view.ne(0)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "tensor([1.8110], requires_grad=True)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:36:23.520102Z",
     "start_time": "2022-03-30T13:36:23.505633Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-0.6570762639939423"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.randn()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:16:36.951960Z",
     "start_time": "2022-03-30T13:16:36.938996Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.float32"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:16:36.966920Z",
     "start_time": "2022-03-30T13:16:36.952958Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([1.8110])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w.data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:16:36.981880Z",
     "start_time": "2022-03-30T13:16:36.967918Z"
    }
   },
   "outputs": [],
   "source": [
    "learning_rate = 0.001\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:32:27.124723Z",
     "start_time": "2022-03-30T13:32:27.113752Z"
    }
   },
   "outputs": [
    {
     "ename": "RuntimeError",
     "evalue": "Numpy is not available",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mRuntimeError\u001b[0m                              Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[17], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m X \u001b[38;5;241m=\u001b[39m \u001b[43mtorch\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_numpy\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mEducation\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvalues\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mreshape\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mtype(torch\u001b[38;5;241m.\u001b[39mFloatTensor)\n\u001b[0;32m      2\u001b[0m Y \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mfrom_numpy(data\u001b[38;5;241m.\u001b[39mIncome\u001b[38;5;241m.\u001b[39mvalues)\u001b[38;5;241m.\u001b[39mtype(torch\u001b[38;5;241m.\u001b[39mFloatTensor)\n",
      "\u001b[1;31mRuntimeError\u001b[0m: Numpy is not available"
     ]
    }
   ],
   "source": [
    "X = torch.from_numpy(data.Education.values.reshape(-1, 1)).type(torch.FloatTensor)\n",
    "Y = torch.from_numpy(data.Income.values).type(torch.FloatTensor)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:34:13.633571Z",
     "start_time": "2022-03-30T13:34:13.617108Z"
    }
   },
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'X' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[16], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mX\u001b[49m\u001b[38;5;241m.\u001b[39mshape\n",
      "\u001b[1;31mNameError\u001b[0m: name 'X' is not defined"
     ]
    }
   ],
   "source": [
    "X.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:35:54.075747Z",
     "start_time": "2022-03-30T13:35:54.065775Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:35:12.625071Z",
     "start_time": "2022-03-30T13:35:12.617093Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([1])\n",
      "torch.Size([])\n",
      "torch.Size([1])\n"
     ]
    }
   ],
   "source": [
    "for x, y in zip(X, Y):\n",
    "    print(x.shape)\n",
    "    print(y.shape)\n",
    "    y_pred = torch.matmul(x, w) + b\n",
    "    print(y_pred.shape)\n",
    "    break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:16:37.011800Z",
     "start_time": "2022-03-30T13:16:36.998836Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.float32"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:37:22.142124Z",
     "start_time": "2022-03-30T13:36:58.712796Z"
    }
   },
   "outputs": [],
   "source": [
    "# 定义训练过程\n",
    "for epoch in range(5000):\n",
    "    for x, y in zip(X, Y):\n",
    "        y_pred = torch.matmul(x, w) + b\n",
    "        # 损失函数\n",
    "        loss = (y - y_pred).pow(2).sum()\n",
    "        \n",
    "        # pytorch对一个变量多次求导, 求导的结果会累加起来. \n",
    "        if w.grad is not None:\n",
    "            # 重置w的导数\n",
    "            w.grad.data.zero_()\n",
    "        if b.grad is not None:\n",
    "            b.grad.data.zero_()\n",
    "            \n",
    "        # 反向传播, 即求w,b的导数\n",
    "        loss.backward()\n",
    "        \n",
    "        # 更新w,b\n",
    "        with torch.no_grad():\n",
    "            \n",
    "            w.data -= w.grad.data * learning_rate\n",
    "            b.data -= b.grad.data * learning_rate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:37:25.836322Z",
     "start_time": "2022-03-30T13:37:25.825351Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([5.1266], requires_grad=True)"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "w"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:37:28.003549Z",
     "start_time": "2022-03-30T13:37:27.993575Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([-32.6962], requires_grad=True)"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:18:23.281497Z",
     "start_time": "2022-03-30T13:18:23.152841Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x2137b28a2b0>]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(data.Education, data.Income)\n",
    "plt.plot(X.numpy(), (torch.matmul(X, w) + b).data.numpy(), c='r')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### pytorch实现线性回归--封装写法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:22:40.197914Z",
     "start_time": "2022-03-30T13:22:40.185946Z"
    }
   },
   "outputs": [],
   "source": [
    "from torch import nn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:32:33.496853Z",
     "start_time": "2022-03-30T13:32:33.480896Z"
    }
   },
   "outputs": [],
   "source": [
    "# 和tensorflow中的Dense一个意思\n",
    "# wx + b\n",
    "model = nn.Linear(1, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:32:33.683355Z",
     "start_time": "2022-03-30T13:32:33.665403Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Linear(in_features=1, out_features=1, bias=True)"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:32:33.854896Z",
     "start_time": "2022-03-30T13:32:33.849910Z"
    }
   },
   "outputs": [],
   "source": [
    "# 定义损失函数\n",
    "loss_fn = nn.MSELoss()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:32:34.038419Z",
     "start_time": "2022-03-30T13:32:34.025946Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object Module.parameters at 0x000002137B336E08>"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 即W\n",
    "model.parameters()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:32:34.220932Z",
     "start_time": "2022-03-30T13:32:34.203978Z"
    }
   },
   "outputs": [],
   "source": [
    "# 定义优化器\n",
    "# 优化器的第一个参数必须是要更新的模型中的参数\n",
    "opt = torch.optim.SGD(model.parameters(), lr=0.001)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:33:06.063909Z",
     "start_time": "2022-03-30T13:32:34.674725Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\2005\\.venv\\lib\\site-packages\\torch\\nn\\modules\\loss.py:528: UserWarning: Using a target size (torch.Size([1])) that is different to the input size (torch.Size([])). This will likely lead to incorrect results due to broadcasting. Please ensure they have the same size.\n",
      "  return F.mse_loss(input, target, reduction=self.reduction)\n"
     ]
    }
   ],
   "source": [
    "# 训练\n",
    "for epoch in range(5000):\n",
    "    for x, y in zip(X, Y):\n",
    "        y_pred = model(x)\n",
    "        loss = loss_fn(y, y_pred)\n",
    "        # 梯度清零操作\n",
    "        opt.zero_grad()\n",
    "        loss.backward()\n",
    "        # 更新操作\n",
    "        opt.step()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:33:37.894409Z",
     "start_time": "2022-03-30T13:33:37.876458Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Parameter containing:\n",
       "tensor([[5.1267]], requires_grad=True)"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# w\n",
    "model.weight"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2022-03-30T13:33:41.497324Z",
     "start_time": "2022-03-30T13:33:41.481367Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Parameter containing:\n",
       "tensor([-32.6986], requires_grad=True)"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# b\n",
    "model.bias"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
